#include <iostream>
#include <malloc.h>
#include <stdlib.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
using namespace std;

typedef int Status;

typedef struct Point
{
    int x, y;
    void SpotPoint(int x, int y)
    {
        this->x = x;
        this->y = y;
    }
} Point;

typedef class Step
{
public:
    int num;
    Point point;
    Step()
    {
        //无参构造函数
    }
    Step(int num, Point p)
    {
        this->num = num;
        this->point.x = p.x;
        this->point.y = p.y;
    }
    void Show()
    {
        cout << "[" << this->num << "]"
             << "(" << this->point.x << "," << this->point.y << ")"
             << "  ";
    }
} ElemType;

#define MAXQSIZE 100
typedef struct
{
    //循环队列的结构
    ElemType *base;
    int front, rear;
} SqQueue;

Status InitQueue(SqQueue &Q)
{
    /*
     *循环队列的初始化
     */
    Q.base = (ElemType *)malloc(sizeof(ElemType) * MAXQSIZE);
    if (!Q.base)
        exit(OVERFLOW);
    Q.front = Q.rear = 0;
    return OK;
}

int QueueLength(SqQueue Q)
{
    /*
     *输出循环列表Q的长度
     */

    return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
bool QueueEmpty(SqQueue Q)
{
    /*
     *判断循环列表Q是否为空
     */

    return Q.front == Q.rear;
}

bool QueueFull(SqQueue Q)
{
    /*
     *判断循环列表Q是否已满
     */

    return (Q.rear + 1) % MAXQSIZE == Q.front;
}

Status EnQueue(SqQueue &Q, ElemType e)
{
    /*
     *入队
     */

    if (QueueFull(Q))
        return ERROR;
    Q.base[Q.rear] = e;
    Q.rear = (Q.rear + 1) % MAXQSIZE;
    return OK;
}

Status DeQueue(SqQueue &Q, ElemType e)
{
    /*
     *出队
     */

    if (QueueEmpty(Q))
        return ERROR;
    e = Q.base[Q.front];
    Q.front = (Q.front + 1) % MAXQSIZE;
    return OK;
}
ElemType DeQueue(SqQueue &Q)
{
    /*
     *出队
     */
    ElemType e;
    e = Q.base[Q.front];
    Q.front = (Q.front + 1) % MAXQSIZE;
    return e;
}

Status showQueue_dev(SqQueue Q)

{
    if (QueueEmpty(Q))
    {
        cout << "队列为空\n\n";
        return OK;
    }

    cout << "当前队列中元素为:";
    for (int i = 0; i < QueueLength(Q); i++)
    {
        Q.base[(Q.front + i) % MAXQSIZE].Show();
    }
    cout << endl
         << endl;
    return OK;
}

SqQueue Steps;

class Maze
{
public:
    int h, w;
    char WALL, WAY;
    char **pos;
    Maze(int h, int w, char wall = '#', char way = '.')
    {
        this->h = h;
        this->w = w;
        this->WALL = wall;
        this->WAY = way;
        this->pos = (char **)malloc(sizeof(char *) * h); // sizeof(int*),不能少*，一个指针的内存大小，每个元素是一个指针。
        for (int i = 0; i < h; i++)
        {
            this->pos[i] = (char *)malloc(sizeof(char) * w);
        }
    }
    void SetPos(string posStr)
    {
        int p = 0;
        int i = 0;
        int j = 0;
        while (posStr[p] != '\0')
        {
            if (posStr[p] == '\n')
            {
                i++;
                j = 0;
            }
            else
            {
                this->pos[i][j] = posStr[p];
                j++;
            }

            p++;
        }
    }

    void ShowMaze_dev()
    {
        cout << "maze is:\n";
        for (int i = 0; i < this->h; i++)
        {
            for (int j = 0; j < this->w; j++)
                cout << this->pos[i][j];
            cout << endl;
        }
        cout << endl;
    }
    /* Point NextPos(Point curPos)
     {
         Point nextPos = curPos;

         if (curPos.y + 1<this->w&&this->pos[curPos.x][curPos.y + 1] == '.')
             nextPos.y++;
         else if (curPos.x+1<this->h&&this->pos[curPos.x + 1][curPos.y] == '.')
             nextPos.x++;
         else if (curPos.y - 1 >=0 && this->pos[curPos.x][curPos.y - 1] == '.')
             nextPos.y--;
         else if (curPos.x - 1 >= 0 && this->pos[curPos.x - 1][curPos.y] == '.')
             nextPos.x--;

         return nextPos;
     }*/
    void Next(Step cur)
    {
        Point p = cur.point;
        int num = cur.num;
        int x = p.x;
        int y = p.y;

        if (y + 1 < w && (pos[x][y + 1] == '.' || pos[x][y + 1] == 'G'))
        {
            Point newP = p;
            newP.y++;
            Step ans(num + 1, newP);
            EnQueue(Steps, ans);
            this->pos[p.x][p.y] = '1';
        }
        if (x + 1 < h && (pos[x + 1][y] == '.' || pos[x + 1][y] == 'G'))
        {
            Point newP = p;
            newP.x++;
            Step ans(num + 1, newP);
            EnQueue(Steps, ans);
            this->pos[p.x][p.y] = '1';
        }
        if (y - 1 >= 0 && (pos[x][y - 1] == '.' || pos[x][y - 1] == 'G'))
        {
            Point newP = p;
            newP.y--;
            Step ans(num + 1, newP);
            EnQueue(Steps, ans);
            this->pos[p.x][p.y] = '1';
        }
        if (x - 1 >= 0 && (pos[x - 1][y] == '.' || pos[x - 1][y] == 'G'))
        {
            Point newP = p;
            newP.x--;
            Step ans(num + 1, newP);
            EnQueue(Steps, ans);
            this->pos[p.x][p.y] = '1';
        }
    }
    Step FindStart(char target = 'S')
    {
        Point p;
        for (int i = 0; i < this->h; i++)
        {
            for (int j = 0; j < this->w; j++)
                if (this->pos[i][j] == target)
                {
                    p.SpotPoint(i, j);
                    Step rst(0, p);
                    return rst;
                }
        }
        p.SpotPoint(0, 0);
        Step rst(0, p);
        return rst;
    }
};

string GetMazeStr(int n, int m)
{
    string mazeStr = "";
    char tmpInput;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            cin >> tmpInput;
            mazeStr += tmpInput;
        }
        mazeStr += "\n";
    }
    mazeStr += '\0';
    return mazeStr;
}

int main()
{
    InitQueue(Steps);
    int n, m;
    cin >> n >> m;

    Maze M(n, m);
    string mazeStr = GetMazeStr(n, m);
    M.SetPos(mazeStr);
    EnQueue(Steps, M.FindStart());

    int currentNum = 0;
    while (true)
    {
        Step currentStep = DeQueue(Steps);

        if (currentStep.num != currentNum)
        {
            _sleep(1000);
            system("cls");
            showQueue_dev(Steps);
            M.ShowMaze_dev();

            currentNum = currentStep.num;
        }

        if (M.pos[currentStep.point.x][currentStep.point.y] == 'G')
        {
            cout << currentStep.num;
            return 0;
        }
        M.Next(currentStep);
    }
}